<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>7.阴影</title>
</head>
<body>
	<canvas id="canvas"></canvas>
	<script type="x-shader/x-vertex" id="vertex">
		attribute vec4 a_position;
		attribute vec2 a_texcoord;

		uniform mat4 u_projection;
		uniform mat4 u_view;
		uniform mat4 u_world;
		uniform mat4 u_shadowViewMatrix;

		varying vec2 v_texcoord;
		varying vec4 v_projectedTexcoord;
		void main(){
  			vec4 worldPosition = u_world * a_position;
			gl_Position = u_projection * u_view * worldPosition;
			v_texcoord = a_texcoord;
			v_projectedTexcoord = u_shadowViewMatrix * worldPosition;

		}
	</script>
	<script type="x-shader/x-fragment" id="fragment">
		precision mediump float;
		
		uniform sampler2D u_texture;
		uniform vec4 u_color;
		varying vec2 v_texcoord;
		varying vec4 v_projectedTexcoord;
		void main(){
			vec3 projectedTexcoord = v_projectedTexcoord.xyz / v_projectedTexcoord.w;
			bool inRange = 
			projectedTexcoord.x >= 0.0 &&
			projectedTexcoord.x <= 1.0 &&
			projectedTexcoord.y >= 0.0 &&
			projectedTexcoord.y <= 1.0;
		vec4 projectedTexColor =vec4(0,0,0,1);
		vec4 texColor = texture2D(u_texture, v_texcoord) *u_color;
		float projectedAmount = inRange ? 1.0 : 0.0;
		gl_FragColor = mix(texColor, projectedTexColor, projectedAmount);
		}
	</script>
	
	<script type="x-shader/x-fragment" id="fragment1">
		precision mediump float;
		uniform vec4 u_color;
		void main(){
			gl_FragColor = u_color;
		}
	</script>
	<script src="https://webglfundamentals.org/webgl/resources/webgl-utils.js"></script>
	<script src="https://webglfundamentals.org/webgl/resources/m4.js"></script>
	<script src="https://webglfundamentals.org/webgl/resources/primitives.js"></script>
	<script src="https://webglfundamentals.org/webgl/resources/texture-utils.js"></script>
	<script src="https://webglfundamentals.org/webgl/resources/chroma.min.js"></script>
	<script>
		/** @type {HTMLCanvasElement} */   
		const canvas=document.getElementById("canvas");
		canvas.width=1000
		canvas.height=500
		const gl=canvas.getContext("webgl")
		const programInfo=webglUtils.createProgramInfo(gl,["vertex","fragment"])
		gl.useProgram(programInfo.program)
		const sphereBufferInfo = primitives.createSphereBufferInfo(
			gl,
			1,  // radius
			12, // subdivisions around
			6,  // subdivisions down
		);
		const planeBufferInfo = primitives.createPlaneBufferInfo(
			gl,
			20,  // width
			20,  // height
			1,   // subdivisions across
			1,   // subdivisions down
		);
		
		function degToRad(d) {
			return d * Math.PI / 180;
		}


		const checkerboardTexture = gl.createTexture();
		gl.bindTexture(gl.TEXTURE_2D, checkerboardTexture);
		gl.texImage2D(
			gl.TEXTURE_2D,
			0,                // mip level
			gl.LUMINANCE,     // internal format
			8,                // width
			8,                // height
			0,                // border
			gl.LUMINANCE,     // format
			gl.UNSIGNED_BYTE, // type
			new Uint8Array([  // data
				0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC,
				0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF,
				0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC,
				0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF,
				0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC,
				0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF,
				0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC,
				0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF,
			]));
		gl.generateMipmap(gl.TEXTURE_2D);
		gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);

		// /* ----平面---- */
		// webglUtils.setUniforms(programInfo, {
		// 	u_view: viewMatrix,
		// 	u_projection: projectionMatrix,
		// 	u_world:m4.translation(0, 0, 0),
		// 	u_color:[0.5, 0.5, 1, 1],
		// 	u_texture:checkerboardTexture
		// });
		// webglUtils.setBuffersAndAttributes(gl, programInfo, planeBufferInfo);
		// webglUtils.drawBufferInfo(gl, planeBufferInfo);
		// /* ----平面---- */
		// /* ----球---- */
		// webglUtils.setUniforms(programInfo, {
		// 	u_view: viewMatrix,
		// 	u_projection: projectionMatrix,
		// 	u_world:m4.translation(2, 3, 4),
		// 	u_color:[1, 0.5, 0.5, 1],
		// 	u_texture:checkerboardTexture
		// });
		// webglUtils.setBuffersAndAttributes(gl, programInfo, sphereBufferInfo);
		// webglUtils.drawBufferInfo(gl, sphereBufferInfo);
		// /* ----球---- */
		//线框
		const programInfo1=webglUtils.createProgramInfo(gl,["vertex","fragment1"])
		const cubeLinesBufferInfo = webglUtils.createBufferInfoFromArrays(gl, {
			position: [
				// 0,  0, -1,
				// 1,  0, -1,
				// 0,  1, -1,
				// 1,  1, -1,
				// 0,  0,  1,
				// 1,  0,  1,
				// 0,  1,  1,
				// 1,  1,  1,

				-1, -1, -1,
				1, -1, -1,
				-1,  1, -1,
				1,  1, -1,
				-1, -1,  1,
				1, -1,  1,
				-1,  1,  1,
				1,  1,  1,
			],
			indices: [
				0, 1,
				1, 3,
				3, 2,
				2, 0,

				4, 5,
				5, 7,
				7, 6,
				6, 4,

				0, 4,
				1, 5,
				3, 7,
				2, 6,
			],
		});
		function drawScene(projectionMatrix, viewMatrix,shadowViewMatrix){
			/* ----平面---- */
			webglUtils.setUniforms(programInfo, {
				u_view: viewMatrix,
				u_projection: projectionMatrix,
				u_world:m4.translation(0, 0, 0),
				u_color:[0.5, 0.5, 1, 1],
				u_texture:checkerboardTexture,
				u_shadowViewMatrix:shadowViewMatrix
			});

			webglUtils.setBuffersAndAttributes(gl, programInfo, planeBufferInfo);
			webglUtils.drawBufferInfo(gl, planeBufferInfo);
			/* ----平面---- */
			// /* ----球---- */
			// webglUtils.setUniforms(programInfo, {
			// 	u_view: viewMatrix,
			// 	u_projection: projectionMatrix,
			// 	u_world:m4.translation(2, 3, 4),
			// 	u_color:[1, 0.5, 0.5, 1],
			// 	u_texture:checkerboardTexture
			// });
			// webglUtils.setBuffersAndAttributes(gl, programInfo, sphereBufferInfo);
			// webglUtils.drawBufferInfo(gl, sphereBufferInfo);
			/* ----球---- */
			const fBufferInfo = primitives.create3DFBufferInfo(gl);
			webglUtils.setBuffersAndAttributes(gl, programInfo, sphereBufferInfo);

			webglUtils.setUniforms(programInfo, sphereBufferInfo);
			// Set the uniforms
			webglUtils.setUniforms(programInfo, {
				u_view: viewMatrix,
				u_projection: projectionMatrix,
				u_world:m4.translation(2, 3, 4),
				u_color:[1, 0.5, 0.5, 1],
				u_texture:checkerboardTexture,
				u_shadowViewMatrix:shadowViewMatrix
			});

			webglUtils.drawBufferInfo(gl, sphereBufferInfo);

		}
		
		let cameraMatrix = m4.lookAt([2.75,5,7], [0.8, 0,4.7], [0,1,0]);
		let shadow = m4.lookAt([2.,5,4], [0.8, 0,4.7], [0,1,0]);
		
		const aspect = gl.canvas.clientWidth/ gl.canvas.clientHeight;
		const projectionMatrix1 =m4.perspective(degToRad(60), aspect, 0.1,200);

		let textureMatrix = m4.identity();
		textureMatrix = m4.translate(textureMatrix, 0.5, 0.5, 0.5);
		textureMatrix = m4.scale(textureMatrix, 0.5, 0.5, 0.5);

		textureMatrix = m4.multiply(textureMatrix,projectionMatrix1);
		textureMatrix = m4.multiply(textureMatrix,m4.inverse(shadow));
		const shadowViewMatrix = textureMatrix
		const viewMatrix = m4.inverse(cameraMatrix);

		//投影乘视图乘世界

		
		const fieldOfViewRadians = degToRad(60);
		const projectionMatrix =m4.perspective(fieldOfViewRadians, aspect, 1, 2000);

		gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
		gl.enable(gl.CULL_FACE);
		gl.enable(gl.DEPTH_TEST);
		gl.clearColor(0.5, 0, 0, 1);
		gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
		drawScene(projectionMatrix,viewMatrix,shadowViewMatrix)


		let cameraMatrix1 = m4.lookAt([-2.75,5,7], [0.8, 0,4.7], [0,1,0]);
		const viewMatrix1 = m4.inverse(cameraMatrix1);

		gl.useProgram(programInfo1.program)
		// gl.disable(gl.DEPTH_TEST);
		// shadow = m4.scale(shadow, 0.5, 0.5, 0.5);

			const mat = m4.multiply(shadow, m4.inverse(projectionMatrix1));
		webglUtils.setUniforms(programInfo1, {
			u_view:viewMatrix,
			u_projection: projectionMatrix,
			u_world:mat,
			u_color:[0,0,0,1],
		});
		//视图*透视 右*相机 右*透视逆
		webglUtils.setBuffersAndAttributes(gl, programInfo1, cubeLinesBufferInfo);

		// gl.disable(gl.DEPTH_TEST);
		
		webglUtils.drawBufferInfo(gl, cubeLinesBufferInfo,gl.LINES);















		function loadImageTexture(url) {
		// 创建一个纹理
		const texture = gl.createTexture();
		gl.bindTexture(gl.TEXTURE_2D, texture);
		// 用一个 1x1 蓝色像素填充该纹理
		gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
						new Uint8Array([0, 0, 255, 255]));
		// 异步加载一张图片
		const image = new Image();
		image.src = url;
		image.addEventListener('load', function() {
			// 现在图片加载完了，把它拷贝到纹理中
			gl.bindTexture(gl.TEXTURE_2D, texture);
			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA,gl.UNSIGNED_BYTE, image);
			// 假设该纹理的宽高是 2 的整次幂
			console.log("gl.generateMipmap(gl.TEXTURE_2D):",gl.generateMipmap(gl.TEXTURE_2D));;
		});
		return texture;
		}
		const imageTexture = loadImageTexture('/f-texture.png');
	</script>
</body>
</html>